package com.yide.myworld.service.impl;


import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.ObjectMetadata;
import com.yide.myworld.api_result.ResultCode;
import com.yide.myworld.exception.Asserts;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author gehaodong
 * date: 2022/12/13
 * <p>阿里云oss上传的工具类</p>
 */
@Slf4j
public class OssFileCommonService {

    /**
     * 阿里云OSS的相关参数
     */
    @Value("${aliyun.oss.endpoint}")
    private String ossEndPoint;

    @Value("${aliyun.oss.accessKeyId}")
    private String ossAccessKeyId;

    @Value("${aliyun.oss.accessKeySecret}")
    private String ossAccessKeySecret;

    @Value("${aliyun.oss.bucketName}")
    private String oss_bucket_name;


    /**
     * 构建客户端链接对象
     *
     * @return
     */
    public OSS createOssClient() {
        // 创建ClientConfiguration，可配置代理、连接超时、最大连接数等参数。
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        // 设置OSSClient允许打开的最大HTTP连接数，默认为1024个。
        conf.setMaxConnections(2048);
        // 设置Socket层传输数据的超时时间，默认为50000毫秒。
        conf.setSocketTimeout(100000);
        // 设置建立连接的超时时间，默认为50000毫秒。
        conf.setConnectionTimeout(20000);
        // 设置失败请求重试次数，默认为3次。
        conf.setMaxErrorRetry(5);
        // 创建OSSClient实例
        return new OSSClientBuilder().build(ossEndPoint, ossAccessKeyId, ossAccessKeySecret, conf);
    }


    /**
     * @param prefixFilePath 上传的路径前缀（不包含bucketName且不以“/"开头）
     * @param file           MultipartFile格式文件,即前端回传的文件列表
     * @return
     */
    public String uploadOneFile(String prefixFilePath, MultipartFile file) {
        String url = "";
        try {
            OSSClient ossClient = (OSSClient) createOssClient();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            // 获取文件名
            String originalFilename = file.getOriginalFilename();
            //获取文件的名称(不带扩展名)
            String fileName = originalFilename.substring(0, originalFilename.lastIndexOf("."));
            // 获取文件后缀名(带.)
            String suffixName = originalFilename.substring(originalFilename.lastIndexOf("."));
            // 最后上传生成的文件名
            String finalFileName = fileName + "-" + System.currentTimeMillis() + suffixName;
            // oss中的文件夹全路径名
            String objectName = prefixFilePath + "/" + finalFileName;
            // 创建上传文件的元信息，可以通过文件元信息设置HTTP header(设置了才能通过返回的链接直接访问)。
            ObjectMetadata objectMetadata = new ObjectMetadata();
//            objectMetadata.setContentType("image/jpg");
            objectMetadata.setContentDisposition("inline");
            // 文件上传
            ossClient.putObject(oss_bucket_name, objectName, new ByteArrayInputStream(file.getBytes()), objectMetadata);
            // 这里设置图片有效时间 设置了30年
            Date expiration = new Date(System.currentTimeMillis() + 946080000 * 1000);
            url = ossClient.generatePresignedUrl(oss_bucket_name, objectName, expiration).toString();
            //过滤掉请求参数,避免链接过期
            url = url.substring(0, url.indexOf("?"));
            ossClient.shutdown();
            log.info("阿里云OSS的文件url:{}", url);
            return url;
        } catch (IOException e) {
            log.error("文件上传失败,文件名为：{}", file.getOriginalFilename(), e);
        }
        return url;
    }


    /**
     * @param prefixFilePath 上传的路径前缀（不包含bucketName且不以“/"开头）
     * @param file           MultipartFile格式文件,即前端回传的文件列表
     * @return
     */
    public String uploadApkFile(String prefixFilePath, MultipartFile file) {
        String url = "";
        try {
            OSSClient ossClient = (OSSClient) createOssClient();
            // 获取文件名
            String originalFilename = file.getOriginalFilename();
            // oss中的文件夹全路径名
            String objectName = prefixFilePath + "/" + originalFilename;
            // 创建上传文件的元信息，可以通过文件元信息设置HTTP header(设置了才能通过返回的链接直接访问)。
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentDisposition("inline");
            // 文件上传
            ossClient.putObject(oss_bucket_name, objectName, new ByteArrayInputStream(file.getBytes()), objectMetadata);
            // 这里设置图片有效时间 设置了30年
            Date expiration = new Date(System.currentTimeMillis() + 946080000 * 1000);
            url = ossClient.generatePresignedUrl(oss_bucket_name, objectName, expiration).toString();
            // 过滤掉请求参数,避免链接过期
            url = url.substring(0, url.indexOf("?"));
            ossClient.shutdown();
            log.info("阿里云OSS的文件url:{}", url);
        } catch (IOException e) {
            log.error("文件上传失败,文件名为：{}", file.getOriginalFilename(), e);
        }
        return url;
    }


    /**
     * 批量上传图片文件
     *
     * @param prefixFilePath
     * @param files
     * @return
     */
    public List<String> uploadImages(String prefixFilePath, MultipartFile[] files) {
        // 文件类型判断
        for (MultipartFile file : files) {
            //如果不支持
            if (!isUpLoadImageType(file.getOriginalFilename())) {
                Asserts.fail(ResultCode.FILE_TYPE_NOT_SUPPORT);
            }
        }
        List<String> urlList = new ArrayList<>();
        // 文件依次上传
        for (MultipartFile file : files) {
            String s = uploadOneFile(prefixFilePath, file);
            urlList.add(s);
        }
        return urlList;
    }

    /**
     * 上传svga文件 （单个上传）
     *
     * @param prefixFilePath
     * @param file
     * @return
     */
    public String uploadSvga(String prefixFilePath, MultipartFile file) {
        if (!isUpLoadDynamicDiagramType(file.getOriginalFilename())) {
            Asserts.fail(ResultCode.FILE_TYPE_NOT_SUPPORT);
        }
        return uploadOneFile(prefixFilePath, file);
    }


    /**
     * 获取文件拓展名
     *
     * @return
     */
    private String getFileExtendName(String fileName) {
        if (StringUtils.isBlank(fileName)) {
            Asserts.fail(ResultCode.FILE_NAME_CAT_NOT_NULL);
        }
        return fileName.substring(fileName.lastIndexOf(".") + 1);
    }

    /**
     * 上传图片支持的文件类型
     *
     * @param fileName
     * @return
     */
    private boolean isUpLoadImageType(String fileName) {
        String fileExtendName = getFileExtendName(fileName);
        if ("png".equalsIgnoreCase(fileExtendName) ||
                "jpg".equalsIgnoreCase(fileExtendName) ||
                "jpeg".equalsIgnoreCase(fileExtendName) ||
                "svga".equalsIgnoreCase(fileExtendName) ||
                "svg".equalsIgnoreCase(fileExtendName)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 上传动态图支持的文件类型
     *
     * @param fileName
     * @return
     */
    private boolean isUpLoadDynamicDiagramType(String fileName) {
        String fileExtendName = getFileExtendName(fileName);
        if ("svga".equalsIgnoreCase(fileExtendName) ||
                "pag".equalsIgnoreCase(fileExtendName) ||
                "mp4".equalsIgnoreCase(fileExtendName)) {
            return true;
        } else {
            return false;
        }
    }

}
